﻿using Furion;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using LimaLims.Application.Service.Base.Dto;
using LimaLims.Application.Service.Sys;
using LimaLims.Application.Service.TestCenter.Dto;
using LimaLims.Core;
using LimaLims.Core.Const;
using LimaLims.Core.Entity.TestCenter;
using LimaLims.Core.Enum;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using Yitter.IdGenerator;

namespace LimaLims.Application.Service.TestCenter
{
    /// <summary>
    ///不良品处理服务API
    /// </summary>
    [ApiDescriptionSettings(Name = "RejectDeal", Order = 160)]
    [Route("api")]
    public class RejectDealService : IRejectDealService, IDynamicApiController, ITransient
    {
        private readonly IRepository<RejectDeal> _rejectDealRep;
        private readonly IRepository<RejectItem> _rejectItemRep;
        private readonly IGenerateCodeUtilService _generateCodeUtilService;//编码规则
        /// <summary>
        /// 构造函数
        /// </summary>
        public RejectDealService(IRepository<RejectDeal> rejectDealRep, IRepository<RejectItem> rejectItemRep, IGenerateCodeUtilService generateCode)
        {
            _rejectDealRep = rejectDealRep;//不良品处理仓储
            _rejectItemRep = rejectItemRep;
            _generateCodeUtilService = generateCode;
        }

        /// <summary>
        /// 发起单据
        /// </summary>
        [HttpPost("rejectDeal/add")]
        [UnitOfWork]
        public async Task Add(AddRejectDealInput input)
        {
            var isExist = await _rejectDealRep.DetachedEntities.AnyAsync(u => u.ExperimentTaskId == input.ExperimentTaskId);
            if (isExist)
                throw Oops.Oh("已存在相同试验任务的不良品单据！");

            if (string.IsNullOrWhiteSpace(input.Code))
            {
                input.Code = await _generateCodeUtilService.GenerateCode(BusinessType.RejectDeal);
            }

            var rejectDeal = new RejectDeal();
            rejectDeal.Id = YitIdHelper.NextId();
            rejectDeal.Code=input.Code;
            //rejectDeal.IsMRBAdvice = false;
            rejectDeal.ExperimentTaskId = input.ExperimentTaskId;
            rejectDeal.Status = RejectDealStatus.Todo;

            await rejectDeal.InsertNowAsync();

            if (input.Items.Any())
            {
                List<RejectItem> tasks = new List<RejectItem>();
                foreach (RejectItemInput item in input.Items)
                {
                    RejectItem task = new RejectItem
                    {
                        Id= YitIdHelper.NextId(),
                        RejectDealId = rejectDeal.Id,
                        Reason=item.Reason,
                        Remark=item.Remark
                    };
                    tasks.Add(task);
                }
                await _rejectItemRep.InsertAsync(tasks);
            }
        }

        /// <summary>
        /// 单据处理
        /// </summary>
        [HttpPost("rejectDeal/deal")]
        public async Task Deal(EditRejectDealInput input)
        {
            var model = await _rejectDealRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (model == null)
                throw Oops.Oh("不存在此数据！");

            model.IsMRBAdvice = input.IsMRBAdvice;
            model.DealTime=DateTime.Now;
            model.DealUser= App.User?.FindFirst(ClaimConst.CLAINM_NAME)?.Value;
            model.RejectAdvice=input.RejectAdvice;
            model.MRBAdvice=input.MRBAdvice;
            model.Result=input.Result;
            model.Status= RejectDealStatus.Deal;

            await model.UpdateAsync();
        }

        /// <summary>
        /// 详细信息
        /// </summary>
        [HttpGet("rejectDeal/detail")]
        public async Task<RejectDealDetail> Detail(long id)
        {
            var model = await _rejectDealRep.DetachedEntities.Include(s => s.ExperimentTask).FirstOrDefaultAsync(u => u.Id == id);
            if (model == null)
                throw Oops.Oh("不存在此数据！");

            var items = await _rejectItemRep.DetachedEntities.Where(u => u.RejectDealId == model.Id).ToListAsync();

            var rejectDealDetail = model.Adapt<RejectDealDetail>();
            rejectDealDetail.TaskCode = model.ExperimentTask.TaskCode;
            rejectDealDetail.Items = items;
            rejectDealDetail.TaskType = model.ExperimentTask.TaskType;
            rejectDealDetail.TargetCode= model.ExperimentTask.TargetCode;
            rejectDealDetail.TargetName = model.ExperimentTask.TargetName;
            return rejectDealDetail;
        }

        /// <summary>
        /// 分页数据
        /// </summary>
        [HttpGet("rejectDeal/page")]
        public async Task<PageResult<RejectDealOutput>> QueryPage([FromQuery] RejectDealPageInput input)
        {
            var code = !string.IsNullOrEmpty(input.Code?.Trim());
            var taskCode = !string.IsNullOrEmpty(input.TaskCode?.Trim());
            var SearchValue = !string.IsNullOrEmpty(input.SearchValue?.Trim());

            var items = await _rejectDealRep.DetachedEntities
                                         .Include(s => s.ExperimentTask)
                                         .Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
                                         .Where((taskCode, u => EF.Functions.Like(u.ExperimentTask.TaskCode, $"%{input.TaskCode.Trim()}%")))
                                         .Where((SearchValue, u => EF.Functions.Like(u.ExperimentTask.TargetCode, $"%{input.SearchValue.Trim()}%")
                                                                || EF.Functions.Like(u.ExperimentTask.TargetName, $"%{input.SearchValue.Trim()}%")))
                                         .Where(input.IsMRBAdvice.HasValue, u => u.IsMRBAdvice == input.IsMRBAdvice)
                                         .Where(u=>u.Status == input.Status)
                                         .OrderByDescending(u => u.CreatedTime)
                                         .Select(u => new RejectDealOutput
                                         {
                                             Id = u.Id,
                                             Code = u.Code,

                                             TaskCode = u.ExperimentTask.TaskCode,
                                             TaskType = u.ExperimentTask.TaskType,
                                             TargetId = u.ExperimentTask.TargetId,
                                             TargetCode = u.ExperimentTask.TargetCode,
                                             TargetName = u.ExperimentTask.TargetName,
                                             TeamName = u.ExperimentTask.TeamName,
                                             ExperimentUserName = u.ExperimentTask.ExperimentUserName,
                                             ActualEndTime = u.ExperimentTask.ActualEndTime.Value,
                                             ActualStartTime = u.ExperimentTask.ActualStartTime.Value,

                                             IsMRBAdvice = u.IsMRBAdvice,
                                             MRBAdvice = u.MRBAdvice,
                                             RejectAdvice = u.RejectAdvice,
                                             Result = u.Result,
                                             DealUser = u.DealUser,
                                             DealTime = u.DealTime,
                                             CreatedTime = u.CreatedTime.Value,
                                             CreatedUserName = u.CreatedUserName,
                                             Status = u.Status,

                                         }).ToADPagedListAsync(input.PageNo, input.PageSize);

            return items;
        }
    }
}
